from django.utils.encoding import force_unicode
from django.utils.html import conditional_escape
from django.utils.safestring import mark_safe
from django import template

__author__ = 'Sharp'

register = template.Library()

def _html_output(self, normal_row, error_row, row_ender, help_text_html, errors_on_separate_row):
    "Helper function for outputting HTML. Used by as_table(), as_ul(), as_p()."
    top_errors = self.non_field_errors() # Errors that should be displayed above all fields.
    output, hidden_fields = [], []

    for name, field in self.fields.items():
        html_class_attr = ''
        bf = self[name]
        bf_errors = self.error_class([conditional_escape(error) for error in bf.errors]) # Escape and cache in local variable.
        if bf.is_hidden:
            if bf_errors:
                top_errors.extend([u'(Hidden field %s) %s' % (name, force_unicode(e)) for e in bf_errors])
            hidden_fields.append(unicode(bf))
        else:
            # Create a 'class="..."' atribute if the row should have any
            # CSS classes applied.
            css_classes = bf.css_classes()
            if css_classes:
                html_class_attr = ' class="%s"' % css_classes

            error_class = ''
            if bf_errors:
                error_class = ' error'
                if errors_on_separate_row:
                    output.append(error_row % force_unicode(bf_errors))

            if bf.label:
                label = conditional_escape(force_unicode(bf.label))
                # Only add the suffix if the label does not end in
                # punctuation.
                if self.label_suffix:
                    if label[-1] not in ':?.!':
                        label += self.label_suffix
            else:
                label = ''

            if field.help_text:
                help_text = help_text_html % force_unicode(field.help_text)
            else:
                help_text = u''

            output.append(normal_row % {
                'errors': force_unicode(bf_errors),
                'label': force_unicode(label),
                'field': unicode(bf),
                'help_text': help_text,
                'html_class_attr': html_class_attr,
                'error_class': force_unicode(error_class),
                'name': force_unicode(name)
            })

    if top_errors:
        output.insert(0, error_row % force_unicode(top_errors))

    if hidden_fields: # Insert any hidden fields in the last row.
        str_hidden = u''.join(hidden_fields)
        output.append(str_hidden)
    return mark_safe(u'\n'.join(output))

@register.filter
def as_table(self):
    "Returns this form rendered as HTML <tr>s -- excluding the <table></table>."
    return _html_output(
        self,
        error_row = u'<tr><td colspan="2">%s</td></tr>',
        row_ender = u'</td></tr>',
        help_text_html = u'<br /><span class="helptext">%s</span>',
        errors_on_separate_row = False,
        normal_row=
    u"""
    <tr id="id_%(name)s_tr">
        <td width="80%%">
            <div class="control-group %(error_class)s ">
                <label class="control-label" for="id_%(name)s">%(label)s</label>

                <div class="controls">
                    %(field)s
                    <span class="help-block" style="color: red;">%(errors)s</span>
                </div>
            </div>
        </td>
        <td>
            <span id="id_%(name)s_help_block" class="help-block">%(help_text)s</span>
        </td>
    </tr>
    """)

@register.filter
def as_ul(self):
    "Returns this form rendered as HTML <li>s -- excluding the <ul></ul>."
    return self._html_output(
        normal_row = u'<li%(html_class_attr)s>%(errors)s%(label)s %(field)s%(help_text)s</li>',
        error_row = u'<li>%s</li>',
        row_ender = '</li>',
        help_text_html = u' <span class="helptext">%s</span>',
        errors_on_separate_row = False)

@register.filter
def as_p(self):
    "Returns this form rendered as HTML <p>s."
    return self._html_output(
        normal_row = u'<p%(html_class_attr)s>%(label)s %(field)s%(help_text)s</p>',
        error_row = u'%s',
        row_ender = '</p>',
        help_text_html = u' <span class="helptext">%s</span>',
        errors_on_separate_row = True)